package com.vca.service.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.vca.common.constants.Constants;
import com.vca.common.constants.RedisConstatns;
import com.vca.common.constants.VhallConstants;
import com.vca.common.exception.VcaException;
import com.vca.common.model.order.StoreOrder;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.order.StoreOrderStatus;
import com.vca.common.model.system.SystemConfig;
import com.vca.common.model.talk.TalkScheduling;
import com.vca.common.model.user.User;
import com.vca.common.request.PageParamRequest;
import com.vca.common.request.VhallSetCallbackRequest;
import com.vca.common.request.VhallSetKeyRequest;
import com.vca.common.response.VhallAdminListResponse;
import com.vca.common.response.VhallGetCallbackResponse;
import com.vca.common.response.VhallGetKeyResponse;
import com.vca.common.utils.DateUtil;
import com.vca.common.utils.PageUtils;
import com.vca.common.utils.RedisUtil;
import com.vca.common.utils.RestTemplateUtil;
import com.vca.common.vo.VhallKeyVo;
import com.vca.service.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Li
 * @program VCA_Mini_Program
 * @description
 * @classname VhallServiceImpl
 * @since 2022/12/19 13:41:32
 **/

@Slf4j
@Service
public class VhallServiceImpl implements VhallService {

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private TalkSchedulingService talkSchedulingService;

    @Autowired
    private RestTemplateUtil restTemplateUtil;

    @Autowired
    private UserService userService;

    @Autowired
    private StoreOrderService orderService;

    @Autowired
    private StoreOrderInfoService orderInfoService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private StoreOrderStatusService storeOrderStatusService;

    /**
     * @return java.lang.Object
     * @description 获取微吼直播列表
     * @author Li
     * @date 2022/12/19 13:44
     */
    @Override
    public PageInfo<VhallAdminListResponse> list(String status, PageParamRequest pageParamRequest) {
        HashMap<String, String> info = systemConfigService.info(161);
        int count = pageParamRequest.getPage()>1?(pageParamRequest.getPage()-1) * pageParamRequest.getLimit():pageParamRequest.getPage()-1;
        Map<String, String> param = new HashMap<>();
        param.put("account", info.get("vhall_account"));
        param.put("password", info.get("vhall_password"));
        param.put("auth_type", "1");
        if (ObjectUtil.isNotEmpty(status)) {
            param.put("status", status);
        }
        param.put("pos", Integer.toString(count));
        param.put("limit", Integer.toString(pageParamRequest.getLimit()));
        String jsonData = restTemplateUtil.postJsonData(VhallConstants.VHALL_URL + VhallConstants.VHALL_WEBINAR_LIST_URL, JSON.parseObject(JSON.toJSONString(param)));
        log.info("jsonData-------------------------------->{}", jsonData);
        JSONObject jsonObject = JSON.parseObject(jsonData);
        String code = jsonObject.get("code").toString();
        List<VhallAdminListResponse> responses = new ArrayList<VhallAdminListResponse>();
        if (code.equals("200")) {
            String data = jsonObject.get("data").toString();
            JSONObject dataJson = JSON.parseObject(data);
            String lists = dataJson.get("lists").toString();
            String total = dataJson.get("total").toString();
            List<Map> maps = JSON.parseArray(lists, Map.class);
            for (int i = 0; i < count; i++) {
                VhallAdminListResponse response = new VhallAdminListResponse();
                responses.add(response);
            }
            maps.forEach(e -> {
                VhallAdminListResponse response = new VhallAdminListResponse();
                response.setCoverImage(e.get("thumb").toString());
                response.setStatus(e.get("status").toString());
                response.setTitle(e.get("subject").toString());
                response.setWebinarId(e.get("webinar_id").toString());
                response.setTopics(e.get("topics").toString());
                response.setStartTime(e.get("start_time").toString());
                responses.add(response);
            });
            int size = responses.size();
            if (size <Integer.parseInt(total)){
                for (int i = 0; i < Integer.parseInt(total) - size; i++) {
                    VhallAdminListResponse response = new VhallAdminListResponse();
                    responses.add(response);
                }
            }
        }
        return PageUtils.startPage(responses, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    /**
     * @param json
     * @return boolean
     * @description 微吼直播状态回调
     * @author Li
     * @date 2022/12/27 15:32
     */
    @Override
    public boolean callBack(String json) {
        log.info("json-------------------------------->{}", json);
        JSONObject jsonObject = JSON.parseObject(json.toString());
        String methodId = jsonObject.get("method_id").toString();
        List<TalkScheduling> list = new ArrayList<TalkScheduling>();
        if (methodId.equals("1")) {
            String webinarId = jsonObject.get("webinar_id").toString();
            String type = jsonObject.get("type").toString();
            list = talkSchedulingService.list(new LambdaQueryWrapper<TalkScheduling>().eq(TalkScheduling::getLiveId, webinarId));
            list.forEach(e -> {
                e.setLiveStatus(Integer.valueOf(type));
            });
        } else if (methodId.equals("2")) {
            String recordId = jsonObject.get("record_id").toString();
        } else if (methodId.equals("3")) {
            String recordId = jsonObject.get("record_id").toString();
        } else {

        }
        if (ObjectUtil.isNotEmpty(list)) {
            List<TalkScheduling> schedulings = list;
            return transactionTemplate.execute(e -> {
                return talkSchedulingService.updateBatchById(schedulings);
            });
        }
        return true;
    }

    /**
     * @param request
     * @return boolean
     * @description 设置微吼回调地址
     * @author Li
     * @date 2022/12/28 9:55
     */
    @Override
    public boolean setCallback(VhallSetCallbackRequest request) {
        HashMap<String, String> info = systemConfigService.info(161);
        Map<String, String> param = new HashMap<>();
        param.put("account", info.get("vhall_account"));
        param.put("password", info.get("vhall_password"));
        param.put("auth_type", "1");
        if (ObjectUtil.isNotEmpty(request.getType())) {
            param.put("type", request.getType().toString());
        }
        if (ObjectUtil.isNotEmpty(request.getSecretKey())) {
            param.put("secret_key", request.getSecretKey());
        }
        if (ObjectUtil.isNotEmpty(request.getCallbackUrl())) {
            param.put("callback_url", request.getCallbackUrl());
        }
        if (ObjectUtil.isNotEmpty(request.getCallbackEvent())) {
            param.put("callback_event", request.getCallbackEvent().toString());
        }
        String jsonData = restTemplateUtil.postJsonData(VhallConstants.VHALL_URL + VhallConstants.VHALL_CALLBACK_SET_EVENT_URL, JSON.parseObject(JSON.toJSONString(param)));
        log.info("jsonData-------------------------------->{}", jsonData);
        JSONObject jsonObject = JSON.parseObject(jsonData);
        String code = jsonObject.get("code").toString();
        return code.equals("200") ? true : false;
    }

    /**
     * @return com.vca.common.response.VhallGetCallbackResponse
     * @description 查询回调事件
     * @author Li
     * @date 2022/12/28 10:21
     */
    @Override
    public VhallGetCallbackResponse getCallback() {
        HashMap<String, String> info = systemConfigService.info(161);
        Map<String, String> param = new HashMap<>();
        param.put("account", info.get("vhall_account"));
        param.put("password", info.get("vhall_password"));
        param.put("auth_type", "1");
        String jsonData = restTemplateUtil.postJsonData(VhallConstants.VHALL_URL + VhallConstants.VHALL_CALLBACK_GET_EVENT_URL, JSON.parseObject(JSON.toJSONString(param)));
        JSONObject jsonObject = JSON.parseObject(jsonData);
        String data = jsonObject.get("data").toString();
        JSONObject dataJson = JSON.parseObject(data);
        String callbackUrl = dataJson.get("callback_url").toString();
        String callbackEvent = dataJson.get("callback_event").toString();
        String secretKey = dataJson.get("secret_key").toString();
        VhallGetCallbackResponse response = new VhallGetCallbackResponse();
        response.setCallbackUrl(callbackUrl);
        response.setPrivateKey(secretKey);
        response.setCallbackEvent(callbackEvent);
        List<SystemConfig> list = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(callbackUrl)) {
            SystemConfig url = new SystemConfig();
            url.setTitle("vhall_callback_url");
            url.setName("vhall_callback_url");
            url.setFormId(161);
            url.setValue(callbackUrl);
            url.setStatus(true);
            list.add(url);
        }
        if (ObjectUtil.isNotEmpty(secretKey)) {
            SystemConfig key = new SystemConfig();
            key.setTitle("vhall_secret_key");
            key.setName("vhall_secret_key");
            key.setFormId(161);
            key.setValue(secretKey);
            key.setStatus(true);
            list.add(key);
        }
        Boolean execute = transactionTemplate.execute(e -> {
            systemConfigService.saveOrUpdateBatch(list);
            return Boolean.TRUE;
        });
        if (!execute) {
            throw new VcaException("查询失败");
        }
        return response;
    }

    /**
     * @param request
     * @return java.lang.String
     * @description 设置VhallKey值验证
     * @methodName setKey
     * @author Li
     * @date 2022/12/29 9:20
     */
    @Override
    public String setKey(VhallSetKeyRequest request) {
        List<SystemConfig> list = new ArrayList<>();
        HashMap<String, String> info = systemConfigService.info(161);
        Map<String, String> param = new HashMap<>();
        param.put("account", info.get("vhall_account"));
        param.put("password", info.get("vhall_password"));
        param.put("auth_type", "1");
        if (ObjectUtil.isNotEmpty(request.getExistAuth())) {
            if (ObjectUtil.isEmpty(request.getAuthUrl())) {
                throw new VcaException("Key值验证不可为空");
            }
            param.put("exist_3rd_auth", request.getExistAuth().toString());
            param.put("auth_url", request.getAuthUrl());
            SystemConfig key = new SystemConfig();
            key.setTitle("vhall_auth_key_url");
            key.setName("vhall_auth_key_url");
            key.setFormId(161);
            key.setValue(request.getAuthUrl());
            key.setStatus(true);
            list.add(key);
            SystemConfig existAuth = new SystemConfig();
            existAuth.setTitle("vhall_exist_auth");
            existAuth.setName("vhall_exist_auth");
            existAuth.setFormId(161);
            existAuth.setValue(request.getExistAuth().toString());
            existAuth.setStatus(true);
            list.add(existAuth);
        }
        if (ObjectUtil.isNotEmpty(request.getFailureUrl())) {
            SystemConfig failureUrl = new SystemConfig();
            failureUrl.setTitle("vhall_failure_url");
            failureUrl.setName("vhall_failure_url");
            failureUrl.setFormId(161);
            failureUrl.setValue(request.getFailureUrl());
            failureUrl.setStatus(true);
            param.put("failure_url", request.getFailureUrl());
            list.add(failureUrl);
        }
        if (ObjectUtil.isNotEmpty(request.getCoverChild())) {
            SystemConfig coverChild = new SystemConfig();
            coverChild.setTitle("vhall_cover_child");
            coverChild.setName("vhall_cover_child");
            coverChild.setFormId(161);
            coverChild.setValue(request.getCoverChild().toString());
            coverChild.setStatus(true);
            param.put("vhall_cover_child", request.getFailureUrl());
            list.add(coverChild);
            param.put("cover_child", request.getCoverChild().toString());
        }
        String jsonData = restTemplateUtil.postJsonData(VhallConstants.VHALL_URL + VhallConstants.VHALL_CALLBACK_SET_KEY_URL, JSON.parseObject(JSON.toJSONString(param)));
        log.info("jsonData-------------------------------->{}", jsonData);
        JSONObject jsonObject = JSON.parseObject(jsonData);
        String code = jsonObject.get("code").toString();
        Boolean execute = transactionTemplate.execute(e -> {
            systemConfigService.saveOrUpdateBatch(list);
            return Boolean.TRUE;
        });
        if (!execute) {
            throw new VcaException("修改失败");
        }
        if (!code.equals("200")) {
            return "设置失败";
        }
        return "设置成功";
    }

    /**
     * @param talkId
     * @return java.lang.String
     * @description 生成Key值
     * @methodName generateKey
     * @author Li
     * @date 2022/12/29 9:45
     */
    @Override
    public String generateKey(Long talkId) {
        log.info("----------talkId:"+talkId);
        User user = userService.getInfo();
        TalkScheduling talkScheduling = talkSchedulingService.getOne(new LambdaQueryWrapper<TalkScheduling>().eq(TalkScheduling::getTalkId, talkId).eq(TalkScheduling::getIsDeleted, 0));
        if (ObjectUtil.isEmpty(talkScheduling)){
            throw new VcaException("无观看权限");
        }
        List<StoreOrder> orders = orderService.getTalkOrderByScheduleId(talkId, user.getUid());
        if (ObjectUtil.isEmpty(orders)) {
            throw new VcaException("无观看权限");
        }
        String tokenStr = UUID.randomUUID().toString().replace("-", "");
        VhallKeyVo vhallKeyVo = new VhallKeyVo(talkId, user.getUid(), tokenStr);
//        VhallKeyVo vhallKeyVo = new VhallKeyVo(scheduledId, 1, tokenStr);
        List<Integer> statusIds = storeOrderStatusService.list(
                        Wrappers.<StoreOrderStatus>lambdaQuery()
                                .in(StoreOrderStatus::getOid, orders.stream().map(StoreOrder::getId).collect(Collectors.toList()))
                                .eq(StoreOrderStatus::getChangeType, Constants.ORDER_LOG_HEXIAO))
                .stream().map(StoreOrderStatus::getOid).collect(Collectors.toList());
        List<Integer> ids = orders.stream().map(StoreOrder::getId).collect(Collectors.toList()).stream().filter(item -> !statusIds.contains(item)).collect(Collectors.toList());
        List<String> orderIds = orders.stream().filter(e -> e.getStatus().equals(1)).collect(Collectors.toList()).stream().map(StoreOrder::getOrderId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(orderIds)){
            transactionTemplate.execute(e -> {
                talkSchedulingService.update(new LambdaUpdateWrapper<TalkScheduling>().eq(TalkScheduling::getId, talkScheduling.getId()).eq(TalkScheduling::getIsDeleted, 0).set(TalkScheduling::getNumberOfParticipants, talkScheduling.getNumberOfParticipants() + orderIds.size()));
                orderService.update(new LambdaUpdateWrapper<StoreOrder>().in(StoreOrder::getOrderId, orderIds).set(StoreOrder::getStatus, 2));
                orderInfoService.update(new LambdaUpdateWrapper<StoreOrderInfo>().in(StoreOrderInfo::getOrderNo, orderIds).set(StoreOrderInfo::getStatus, 2).set(StoreOrderInfo::getWriteOffTime, DateUtil.nowDate(Constants.DATE_FORMAT)));
                ids.forEach(o -> {
                    storeOrderStatusService.createLog(o, Constants.ORDER_LOG_HEXIAO, 0, "核销完成");
                });
                return Boolean.TRUE;
            });
        }
        redisUtil.set(Constants.VHALL_KEY_PREFIX + tokenStr, JSON.toJSONString(vhallKeyVo),Long.valueOf(systemConfigService.getValueByKey("vhall_key_validity")), TimeUnit.MINUTES);
        return tokenStr;
    }

    /**
     * @param params
     * @return java.lang.String
     * @description k值校验
     * @methodName check
     * @author Li
     * @date 2022/12/29 11:07
     */
    @Override
    public String check(Map<String, Object> params) {
        log.info("params----------------->{}", params);
        String k = params.get("k").toString();
        if (!redisUtil.exists(Constants.VHALL_KEY_PREFIX + k)) {
            return "fail";
        }
        String jsonString = redisUtil.get(Constants.VHALL_KEY_PREFIX + k).toString();
        VhallKeyVo vhallKeyVo = JSON.parseObject(jsonString, VhallKeyVo.class);
        if (!k.equals(vhallKeyVo.getKey())) {
            return "fail";
        }
//        redisUtil.delete(Constants.VHALL_KEY_PREFIX + k);
        return "pass";
    }

    /**
     * @return com.vca.common.response.VhallGetKeyResponse
     * @description 获取VhallKey值参数
     * @methodName getKey
     * @author Li
     * @date 2022/12/30 11:25
     */
    @Override
    public VhallGetKeyResponse getKey() {
        HashMap<String, String> info = systemConfigService.info(161);
        VhallGetKeyResponse response = new VhallGetKeyResponse();
        String authUrl = info.get("vhall_auth_key_url");
        String coverChild = info.get("vhall_cover_child");
        String existAuth = info.get("vhall_exist_auth");
        String failureUrl = info.get("vhall_failure_url");
        response.setAuthUrl(ObjectUtil.isEmpty(authUrl) ? "" : authUrl);
        response.setCoverChild(ObjectUtil.isEmpty(coverChild) ? 0 : Integer.valueOf(coverChild));
        response.setExistAuth(ObjectUtil.isEmpty(existAuth) ? 0 : Integer.valueOf(existAuth));
        response.setFailureUrl(ObjectUtil.isEmpty(failureUrl) ? "" : failureUrl);
        return response;
    }
}
